/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Modelo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;

/**
 *
 * @author felumpe
 */
public class Gramatica {

    ArrayList<String> reservadas = new ArrayList<String>();
    ArrayList<String> aritmeticos = new ArrayList<String>();
    ArrayList<String> logicos = new ArrayList<String>();
    ArrayList<String> simbolos = new ArrayList<String>();

    //gambi ahead!
    public ArrayList<String> preenche_reservadas() {
        ArrayList<String> retorno = new ArrayList<String>();
        retorno.add("IF");
        retorno.add("ELSE");
        retorno.add("WHILE");
        retorno.add("ENTRA");
        retorno.add("SAI");
        retorno.add("FOR");
        retorno.add("BOOLEANO");
        retorno.add("REAL");
        retorno.add("INTEIRO");
        retorno.add("STRING");
        retorno.add("VARIAVEIS");
        retorno.add("PROGRAMA");
        retorno.add("ROTINA");
        return retorno;
    }

    public ArrayList<String> preenche_aritmeticos() {
        ArrayList<String> retorno = new ArrayList<String>();
        retorno.add("+");
        retorno.add("-");
        retorno.add("*");
        retorno.add("/");
        retorno.add("^");
        retorno.add("%");
        retorno.add("=");
        return retorno;
    }

    public ArrayList<String> preenche_logicos() {
        ArrayList<String> retorno = new ArrayList<String>();
        retorno.add("<");
        retorno.add(">");
        retorno.add("!");
        retorno.add("!=");
        retorno.add("==");
        retorno.add("<=");
        retorno.add(">=");
        retorno.add("AND");
        retorno.add("OR");
        return retorno;
    }

    public ArrayList<String> preenche_simbolos() {
        ArrayList<String> retorno = new ArrayList<String>();
        retorno.add("(");
        retorno.add(")");
        retorno.add(";");
        retorno.add("'");
        retorno.add(",");
        retorno.add("}");
        retorno.add("{");
        return retorno;
    }

    public LinkedList<Tokens> classifica(LinkedList<Tokens> tokens, HashMap tabela) /*
     * o metodo vai atualizar a lista de token: alem do lexema agora vai ser
     * setado o tipo dele podem ser simbolos, operadores aritmeticos ou logicos,
     * plavras reservadas, identificadores ou digitos. diferente disso sera erro
     * os IDs serão adicionados na tabela de simbolos (mas através de outro
     * meotodo que será chamado aqui)
     */ {
        reservadas = preenche_reservadas();
        aritmeticos = preenche_aritmeticos();
        logicos = preenche_logicos();
        simbolos = preenche_simbolos();

        LinkedList<Tokens> classificados = new LinkedList<Tokens>();
        for (int i = 0; i < tokens.size(); i++) {
            Tokens aux = new Tokens();
            aux.setLexema(tokens.get(i).getLexema());
            aux.setLinha(tokens.get(i).getLinha());
            classificados.add(aux);
            classificados.get(i).setLexema(tokens.get(i).getLexema());
            String gambi = classificados.get(i).getLexema().toString();
            if (reservadas.contains(classificados.get(i).getLexema())) //palavra reservada
            {
                classificados.get(i).setTipo("palavra_reservada");
            } else {
                if (('\"'==gambi.charAt(0))&&('\"'==gambi.charAt(gambi.length()-1)))
                {
                    classificados.get(i).setTipo("txt_string");
                } else {
                    if (aritmeticos.contains(classificados.get(i).getLexema().toString())) //operador aritmetico
                    {
                        classificados.get(i).setTipo("aritmetico");
                    } else {
                        if (logicos.contains(classificados.get(i).getLexema().toString()))//operador logico
                        {
                            classificados.get(i).setTipo("logico");
                        } else {
                            if (simbolos.contains(classificados.get(i).getLexema().toString()))//simbolo
                            {
                                classificados.get(i).setTipo("simbolo");
                            } else {
                                try {
                                    if ((Character.isDigit(classificados.get(i).getLexema().toString().charAt(0))) || (classificados.get(i).getLexema().toString().charAt(0) == '-')) //pode ser um valor numerico
                                    {
                                        for (int j = 0; j < classificados.get(i).getLexema().toString().length(); j++)// verifica char a char
                                        {
                                            if(!(Character.isDigit(classificados.get(i).getLexema().toString().charAt(j)) || (classificados.get(i).getLexema().toString().charAt(j) == '-'))) //começou com numero, precisa ser numero
                                            {
                                                classificados.get(i).setTipo("erro digito");
                                                break;
                                            }
                                            if (j == classificados.get(i).getLexema().toString().length() - 1) //sera vdd na ultima iteracao
                                            {
                                                classificados.get(i).setTipo("digito");
                                            }
                                        }
                                    } else {
                                        if (Character.isLetter(classificados.get(i).getLexema().toString().charAt(0))) //pode ser um ID
                                        {
                                            for (int j = 0; j < classificados.get(i).getLexema().toString().length(); j++)// char a char
                                            {                                                                         //começou com letra, resto pode ser alfanumerico
                                                if (!Character.isLetterOrDigit(classificados.get(i).getLexema().toString().charAt(j))) {
                                                    classificados.get(i).setTipo("erro ident");
                                                    break;
                                                }
                                                if (j == classificados.get(i).getLexema().toString().length() - 1) //sera vdd na ultima iteracao
                                                {
                                                    classificados.get(i).setTipo("identificador");

                                                }
                                            }
                                        } else {
                                            System.out.println("erro: variavel não identificada!");
                                            classificados.get(i).setTipo("erro");
                                        }
                                    }
                                } catch (StringIndexOutOfBoundsException x) {
                                }
                            }
                        }
                    }
                }
            }
        } //aqui adiciona na tabela de simbolos se é digito ou identificador
        for (int i = 0; i < classificados.size(); i++) {
            if (((classificados.get(i).getTipo().equals("digito")) || (classificados.get(i).getTipo().equals("identificador"))) && (!(tabela.containsValue(classificados.get(i))))) {
                tabela.put(classificados.get(i).getLexema(), classificados.get(i));
            }
        }
        return classificados;
    }
}
